const {
  getQuestionInfo,
  getQuestionList,
  createQuestion,
  updateQuestion,
  deleteQuestionList,
  getPublishedQuestionInfo,
} = require("../service/question.service");
const {
  getComponentList,
  createComponentList,
  deleteComponentList,
} = require("../service/component.service");
const {
  getAnswerList,
  createAnswer,
  deleteAnswerList,
} = require("../service/answer.service");
const { questionCreateSuccess } = require("../constant/successType");
const { getUserInfo } = require("../service/user.service");
const { formatDate } = require("../common/utils");
const { Op } = require("sequelize");
const {
  questionGetInfoError,
  questionPublishedError,
} = require("../constant/errorType");
const successType = require("../constant/successType");
const errorType = require("../constant/errorType");

class QuestionController {
  // 根据id获取问卷信息
  async getQuestionById(ctx) {
    const { questionId } = ctx.params;
    const { title, isPrompt, desc, is_published } = await getQuestionInfo(
      { id: questionId },
      ctx
    );
    const componentList = await getComponentList({ question_id: questionId });

    ctx.body = {
      code: 0,
      result: {
        title,
        isPrompt,
        desc,
        isPublished: is_published,
        componentList: componentList
          .sort((a, b) => a._index - b._index)
          .map((i) => {
            const {
              question_id,
              is_hidden,
              is_locked,
              _index,
              ...componentInfo
            } = i;
            return {
              ...componentInfo,
              isHidden: is_hidden,
              isLocked: is_locked,
            };
          }),
      },
    };
  }

  // 获取问卷列表
  async getQuestionList(ctx) {
    const { id } = ctx.state.userInfo;
    const { isDeleted } = ctx.query;
    let is_admin;
    const res = await getUserInfo({ id }, ctx)
      .then((userInfo) => {
        is_admin = userInfo.is_admin;
        return getQuestionList({ ...ctx.query, is_admin }, ctx);
      })
      .then(async (questionList) => {
        const { rows } = questionList;
        const questionIds = rows.map((i) => i.id);
        const { list = [] } = await getAnswerList(
          {},
          {
            question_id: {
              [Op.in]: questionIds,
            },
          }
        );
        rows.forEach((i) => {
          i.dataValues.answerCount =
            list.filter((j) => j.question_id === i.id).length || 0;
        });

        return questionList;
      })
      .then(async (questionList) => {
        const { count, rows } = questionList;
        let formatRows = [];

        if (rows.length) {
          formatRows = rows
            .map((i) => i.dataValues)
            .filter((i) => isDeleted || !i.is_deleted)
            .map((i) => {
              const { is_published, is_star, createdAt, updatedAt, ...questionInfo } = i;

              return {
                ...questionInfo,
                isPublished: is_published,
                isStar: is_star,
                createdAt: formatDate(createdAt),
                updatedAt: formatDate(updatedAt),
              };
            });
        }

        return new Promise(async (resolve) => {
          if (!is_admin) return resolve({ total: count, list: formatRows });

          const userInfoList = await Promise.all(
            formatRows.map((i) => getUserInfo({ id: i.createdId }, ctx))
          );
          const formatRowsByAdmin = formatRows.map((i, index) => {
            i.createdBy = userInfoList[index].nick_name;
            return i;
          });

          resolve({ total: count, list: formatRowsByAdmin });
        });
      });

    ctx.body = {
      code: 0,
      result: res,
    };
  }

  // 创建问卷
  async createQuestion(ctx) {
    const { id } = ctx.state.userInfo;
    const res = await createQuestion({ createdId: id }, ctx);

    ctx.body = { ...questionCreateSuccess, result: { id: res.id } };
  }

  // 编辑问卷
  async editQuestion(ctx) {
    const { id, is_admin } = ctx.state.userInfo;
    const { questionId } = ctx.params;
    const { componentList = [], ...questionInfo } = ctx.request.body;
    const { isPublished, isStar, isDeleted } = questionInfo;
    let message;

    if (isPublished && !componentList.length) {
      return (ctx.body = questionPublishedError);
    }
    const whereOpt = { id: questionId };
    if (!is_admin) whereOpt.createdId = id;
    // 更新问卷信息
    await updateQuestion(
      {
        ...questionInfo,
        is_published: isPublished,
        is_star: isStar,
        is_deleted: isDeleted,
      },
      whereOpt
    );
    if (isPublished) {
      message = "发布成功";
    } else if (isStar) {
      message = "标星成功";
    } else if (isDeleted) {
      message = "删除成功";
    } else {
      message = "保存成功";

      // 只有当提供了组件列表时才更新组件，避免意外删除已提交的答卷
      if (componentList.length > 0) {
        // 批量彻底删除旧组件
        await deleteComponentList({ question_id: questionId });
        // 批量彻底删除答卷
        await deleteAnswerList({ question_id: questionId });
        // 批量创建新组件
        await createComponentList(
          componentList.map((i, index) => {
            i.question_id = questionId;
            i._index = index;
            i.is_hidden = i.isHidden;
            i.is_locked = i.isLocked;
            delete i.id;
            delete i.isHidden;
            delete i.isLocked;
            delete i.createdAt;
            delete i.updatedAt;

            return i;
          })
        );
      }
    }

    ctx.body = { code: 0, message };
  }

  // 批量编辑问卷
  async editQuestionList(ctx) {
    const { id } = ctx.state.userInfo;
    const { ids, isDeleted } = ctx.request.body;
    const newQuestionInfo = {};
    let message;

    if (isDeleted === false) {
      message = "恢复成功";
      Object.assign(newQuestionInfo, { is_deleted: isDeleted });
    }
    // 更新问卷信息
    await updateQuestion(newQuestionInfo, {
      createdId: id,
      id: {
        [Op.in]: ids, // 使用in操作符过滤指定id数组的数据
      },
    });

    ctx.body = { code: 0, message };
  }

  // 批量彻底删除问卷
  async deleteQuestionList(ctx) {
    const { id } = ctx.state.userInfo;
    const query = ctx.query;
    const ids = query.ids.split(",");
    // 批量彻底删除问卷
    await deleteQuestionList({
      createdId: id,
      id: {
        [Op.in]: ids,
      },
    });
    // 批量彻底删除组件
    await deleteComponentList({
      question_id: {
        [Op.in]: ids,
      },
    });
    // 批量彻底删除答卷
    await deleteAnswerList({
      question_id: {
        [Op.in]: ids,
      },
    });

    ctx.body = successType.questionDeleteSuccess;
  }

  // 复制问卷
  async duplicateQuestion(ctx) {
    const { id } = ctx.state.userInfo;
    const { questionId } = ctx.params;
    const res = await createQuestion({ createdId: id }, ctx);
    const componentList = await getComponentList({ question_id: questionId });
    // 创建新组件
    await createComponentList(
      componentList.map((i) => {
        delete i.id;
        // 将组件分配给新的问卷
        i.question_id = res.id;
        i.is_hidden = i.isHidden;
        delete i.isHidden;
        i.is_locked = i.isLocked;
        delete i.isLocked;
        return i;
      })
    );

    ctx.body = {
      ...successType.questionDuplicateSuccess,
      result: { id: res.id },
    };
  }

  // 根据id获取问卷的统计信息
  async getQuestionStatListById(ctx) {
    const { questionId } = ctx.params;
    const { page = 0, pageSize = 15 } = ctx.query;
    const { total, list } = await getAnswerList(
      {
        offset: (page - 1) * pageSize,
        limit: pageSize - 0,
      },
      { question_id: questionId },
      ctx
    );

    ctx.body = {
      code: 0,
      result: {
        total,
        list: list.map((i) => {
          const { id, answers, createdAt } = i;
          return {
            id,
            ...answers,
            createdAt: formatDate(createdAt),
          };
        }),
      },
    };
  }

  // 根据id获取问卷单个组件的统计信息
  async getQuestionComponentStatById(ctx) {
    const { questionId, componentId } = ctx.params;
    const stat = [];
    const componentList = await getComponentList({
      question_id: questionId,
      id: componentId,
    });
    const { type, props } = componentList[0];
    switch (type) {
      case "questionRadio":
        const { options } = props;
        options.forEach((i) =>
          stat.push({ value: i.value, name: i.label, count: 0 })
        );
        break;
      case "questionCheckbox":
        const { list } = props;
        list.forEach((i) =>
          stat.push({ value: i.value, name: i.label, count: 0 })
        );
        break;
    }
    const { list } = await getAnswerList({}, { question_id: questionId }, ctx);
    list.forEach((i) => {
      const { answers } = i;
      const answer = answers[componentId];
      if (answer) {
        if (Array.isArray(answer)) {
          answer.forEach((a) => {
            const item = stat.find((v) => v.value === a);
            if (item) item.count++;
          });
        } else {
          const item = stat.find((v) => v.value === answer);
          if (item) item.count++;
        }
      }
    });

    ctx.body = {
      code: 0,
      result: { stat },
    };
  }

  // 客户端
  // 根据id获取已发布的问卷信息
  async getPublishedQuestionById(ctx) {
    const { questionId } = ctx.params;
    const { answerId } = ctx.query;
    const res = await getPublishedQuestionInfo(questionId);
    const answerRes =
      answerId &&
      (await getAnswerList({}, { id: answerId, question_id: questionId }));
    if (res && res.dataValues) {
      const { title, desc, is_published } = res;
      const componentList = await getComponentList({ question_id: questionId });

      ctx.body = {
        code: 0,
        result: {
          title,
          desc,
          isPublished: is_published,
          componentList: componentList
            .sort((a, b) => a._index - b._index)
            .map((i) => {
              const {
                question_id,
                is_hidden,
                is_locked,
                _index,
                ...componentInfo
              } = i;
              if (answerRes && answerRes.list && answerRes.list.length > 0) {
                const { answers } = answerRes.list[0];
                Object.assign(componentInfo, { answer: answers[i.id] });
              }

              return componentInfo;
            }),
        },
      };
    } else {
      ctx.body = questionGetInfoError;
    }
  }

  // 创建答卷
  async createQuestionAnswer(ctx) {
    const { questionId } = ctx.params;
    if (questionId === null || questionId === undefined || questionId === "")
      return (ctx.body = errorType.answerCreateByIdError);

    const list = ctx.request.body;

    if (list.every((i) => !i.value))
      return (ctx.body = errorType.answerCreateByEmptyError);

    // 获取当前问卷的所有组件
    const componentList = await getComponentList({ question_id: questionId });

    // 检查是否有重复提交的唯一性字段
    for (let i = 0; i < list.length; i++) {
      const item = list[i];
      const component = componentList.find((c) => c.id === item.componentId);

      // 如果是questionInput类型组件且设置了isUnique为true
      if (
        component &&
        component.type === "questionInput" &&
        component.props &&
        component.props.isUnique
      ) {
        // 查询数据库中是否已存在相同的答案值
        const { list: existingAnswers } = await getAnswerList(
          {},
          {
            question_id: questionId,
          }
        );

        // 检查是否已存在相同的值
        const isDuplicate = existingAnswers.some((answer) => {
          const answerValue = answer.answers[item.componentId];
          // 空字符串不参与重复值检查
          return (
            answerValue !== "" &&
            answerValue !== null &&
            answerValue !== undefined &&
            answerValue === item.value
          );
        });

        if (isDuplicate) {
          return (ctx.body = {
            code: 1,
            message: `${component.title}不允许提交重复的值`,
            result: null,
          });
        }
      }
    }

    let answers = {};
    list.forEach((i) => {
      answers[i.componentId] = i.value;
    });

    // 处理组件的isRandom属性
    for (let i = 0; i < list.length; i++) {
      const item = list[i];
      const component = componentList.find((c) => c.id === item.componentId);

      // 如果是questionCheckbox类型组件且设置了isRandom为true
      if (
        component &&
        component.type === "questionCheckbox" &&
        component.props &&
        component.props.isRandom
      ) {
        // 获取answer值
        const answer = answers[item.componentId];
        if (Array.isArray(answer) && answer.length > 0) {
          // 将answer赋值给prompt
          const prompt = [...answer];
          // 从prompt中随机选择一个作为新的answer
          const randomIndex = Math.floor(Math.random() * prompt.length);
          answers[item.componentId] = [prompt[randomIndex]];
        }
      }
    }

    const { id: answerId } = await createAnswer({
      question_id: questionId,
      answers,
    });
    const questionInfo = await getPublishedQuestionInfo(questionId);
    const isPrompt = questionInfo ? questionInfo.isPrompt : false;
    let result = { questionId };

    if (isPrompt) result.answerId = answerId;

    ctx.body = {
      ...successType.answerCreateSuccess,
      result,
    };
  }

  // 获取使用统计信息
  async getUsageInfo(ctx) {
    const { count: questionCount, rows: questionList } =
      await getQuestionList();
    const { total: answerCount } = await getAnswerList();

    ctx.body = {
      code: 0,
      result: {
        questionCount: questionCount,
        questionPublishedCount: questionList.filter((i) => i.is_published)
          .length,
        answerCount,
      },
    };
  }

  // 删除答卷记录
  async deleteAnswerById(ctx) {
    const { questionId, answerId } = ctx.params;

    if (!questionId || !answerId) {
      return (ctx.body = {
        code: 1,
        message: "缺少必要参数",
      });
    }

    try {
      const res = await deleteAnswerList({
        id: answerId,
        question_id: questionId,
      });

      if (res > 0) {
        ctx.body = {
          code: 0,
          message: "删除成功",
        };
      } else {
        ctx.body = {
          code: 1,
          message: "删除失败，未找到对应的答卷记录",
        };
      }
    } catch (err) {
      console.error(err);
      ctx.body = {
        code: 1,
        message: "删除失败",
        error: err.message,
      };
    }
  }
}

module.exports = new QuestionController();
